/**
 * 文件名：@StructureJsonResultModelProcessor.java <br/>
 * 包名：cn.efunbox.afw.core.mvc.result <br/>
 * 项目名：afw-core <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.core.mvc.result;

import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.efunbox.afw.core.ErrorModel;
import cn.efunbox.afw.core.decoupling.ErrorsHolder;
import cn.efunbox.afw.core.decoupling.ExtractHolder;
import cn.efunbox.afw.core.decoupling.StatusHolder;
import cn.efunbox.afw.core.entity.Result;
import cn.efunbox.afw.core.entity.Status;
import cn.efunbox.afw.core.mvc.context.Context;
import cn.efunbox.afw.core.util.AfwConstant;

/**
 * 类名：StructureJsonResultModelProcessor  <br />
 *
 * 功能：结构化的Json结果模型处理器
 * 
 * 	返回数据格式：
 * 		{
 * 			header: {
 * 				local: "zh_CN"
 * 			},
 * 			status: {
 * 				code: "0000", // 状态码
 * 				message: "操作成功" // 提示信息
 * 			},
 * 			result: // 业务数据，具体类型由具体业务接口而定
 * 		}
 *
 * @author xtwin <br />
 * 创建时间：2015年12月4日 上午10:52:10  <br />
 * @version 2015年12月4日
 */
public class StructureJsonResultModelProcessor implements ResultModelProcessor {
	
	// 日志记录器
	private static final Log logger = LogFactory.getLog(StructureJsonResultModelProcessor.class);
	
	// 默认状态码
	protected String code = "0000";
	
	// 默认成功时的code
	protected String codeOk = "0000";
	
	// 默认消息
	protected String message = "operate.success";
	
	// 结果提取解析器
	protected ResultExtractParser resultExtractParser;

	/**
	 * 功能: 处理模型数据 <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2015年12月4日 上午10:52:25<br/>
	 * 
	 * @param context
	 * @param model
	 * @return <br/>
	 * @see cn.efunbox.afw.core.mvc.result.ResultModelProcessor#process(cn.efunbox.afw.core.mvc.context.Context, java.util.Map)
	 */
	@Override
	public Object process(Context context, Map<String, Object> model) {
		// 解析状态信息
		Status status = parseStatus(context, model);
		
		// 创建结果对象
		Result result = new Result();
		
		if (null == codeOk || codeOk.equals(status.getCode())) {
			// 在状态码为成功时，过滤并放入数据
			result.setData(filter(context, model));
		}
		
		// 添加响应头
		result.addHeader("local", context.getLocale().toString());
		// 放入状态信息
		result.setStatus(status);
		
		// 日志打印
		if (logger.isDebugEnabled()) {
			logger.debug("the result is : " + result);
		}
		
		return result;
	}
	
	/**
	 * 功能：解析出status对象，不允许返回null <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月10日 上午10:11:36 <br/>
	 */
	protected Status parseStatus(Context context, Map<String, Object> model) {
		// 取出错误信息
		ErrorModel error = ((ErrorsHolder) context).getErrors();
		
		// 状态信息处理
		String code = this.code;
		String message = this.message;
		if (null != error) {
			// 当程序发生错误时，使用错误信息的状态与消息
			code = error.getCode();
			message = error.getMessage();
		} else {
			if (context instanceof StatusHolder) {
				Status status = ((StatusHolder) context).getStatus();
				
				// 检查是否在上下文中设置过状态信息
				if (null != status) {
					code = status.getCode();
					message = status.getMessage();
				}
			}
		}
		
		// 使用计算出的code与message创建status对象
		return new Status(code, message);
	}
	
	/**
	 * 
	 * 功能：过滤数据 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月9日 下午7:01:32 <br/>
	 */
	protected Object filter(Context context, Map<String, Object> model) {
		Object root = model;
		if (model.containsKey(AfwConstant.KEY_ROOT)) {
			// 若设置了json的root值，就取出root对应的值
			root = model.get(AfwConstant.KEY_ROOT);
		}
		
		// 提取字段
		String[] extract = getExtract(context);
		
		if (null != extract && null != root) {
			try {
				// 按提取配置进行数据提取
				root = resultExtractParser.parse(root, extract);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		
		// 将没有处理过的数据置为null，防止数据泄露
		if (root == model) {
			root = null;
		}
		
		return root;
	}
	
	/**
	 * 
	 * 功能：取得提取字段定义 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2015年12月4日 上午11:01:09 <br/>
	 */
	protected String[] getExtract(Context context) {
		if (context instanceof ExtractHolder) {
			return ((ExtractHolder) context).getExtract();
		}
		
		return null;
	}

	/**
	 * @version 2015年12月4日-上午10:57:11
	 */
	public void setCode(String code) {
		this.code = code;
	}

	/**
	 * @version 2015年12月4日-上午10:57:11
	 */
	public void setMessage(String message) {
		this.message = message;
	}

	/**
	 * @version 2015年12月4日-上午10:57:11
	 */
	public void setResultExtractParser(ResultExtractParser resultExtractParser) {
		this.resultExtractParser = resultExtractParser;
	}

	/**
	 * @version 2015年12月10日-上午10:14:18
	 */
	public void setCodeOk(String codeOk) {
		this.codeOk = codeOk;
	}
}
